import json
import random
import threading
from datetime import datetime, timedelta

import psutil
import redis
import uvicorn
from fastapi import Depends
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session
from starlette.responses import HTMLResponse, JSONResponse
from starlette.staticfiles import StaticFiles

from db import SessionLocal
from db.tables import ModelPerformance
from monitor_turbo import main

app = FastAPI()


@app.get("/", response_class=HTMLResponse)
async def read_items():
    with open('front/page/index.html', 'r', encoding='utf-8') as f:
        html_content = f.read()
    return html_content


app.mount("/static", StaticFiles(directory="front/static"), name="static")


@app.on_event("startup")
async def startup_event():
    # 在新线程中运行脚本
    def run_script():
        main()
        # pass

    # 直接调用同步的 flushdb 方法
    redis_client.flushdb()

    # 启动一个新线程执行 monitor_main
    thread = threading.Thread(target=run_script)
    thread.start()


redis_client = redis.Redis(host='localhost', port=6379, db=2, decode_responses=True)


# @app.get("/get_requests")
# def read_requests():
#     # 计算当前时间往前推三秒
#     three_seconds_ago = datetime.now() - timedelta(seconds=3)
#     # 格式化时间戳作为 Redis 的键
#     timestamp_key = three_seconds_ago.strftime("%Y-%m-%d %H:%M:%S")
#
#     # 从 Redis 获取数据
#     result = redis_client.get(timestamp_key)
#     if result is None or result == '':
#         # 如果没有数据或数据为空字符串，返回空的 JSON 对象
#         return JSONResponse(content={})
#
#     try:
#         # 尝试解析 JSON 数据
#         data = json.loads(result)
#     except json.JSONDecodeError:
#         # 如果解析失败，返回错误信息
#         raise HTTPException(status_code=400, detail="无法解析 JSON 数据")
#
#     # 返回解析后的 JSON 对象
#     return JSONResponse(content=data)


@app.get("/get_requests")
def read_requests():
    # 生成 Total 为 100 以内的随机数
    total = random.randint(0, 100)
    # 生成 Normal 为 Total 以内的随机数
    normal = random.randint(0, total)
    # 计算 Anomalous
    anomalous = total - normal

    # 构造返回的 JSON 数据
    data = {
        "Total": total,
        "Normal": normal,
        "Anomalous": anomalous
    }

    # 返回模拟的 JSON 对象
    return JSONResponse(content=data)


def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@app.get("/model_performance")
async def read_performance(type: int, db: Session = Depends(get_db)):
    if type == 0:
        model_name = 'detect_model.joblib'
    elif type == 1:
        model_name = 'detect_model_mini.joblib'
    else:
        raise HTTPException(status_code=400, detail="Invalid type provided")

    data = db.query(ModelPerformance.model_name, ModelPerformance.type, ModelPerformance.precision,
                    ModelPerformance.recall, ModelPerformance.f1_score, ModelPerformance.train_support,
                    ModelPerformance.test_support).filter(ModelPerformance.model_name == model_name).all()
    if not data:
        raise HTTPException(status_code=404, detail="Model not found")

    return {"data": [
        dict(zip(["模型名称", "类型", "精确度", "召回率", "F1分数", "训练集样本数", "测试集样本数"], d)) for d
        in data]}


@app.get("/system_metrics")
def get_system_metrics():
    # 获取CPU使用率
    cpu_usage = psutil.cpu_percent(interval=1)
    # 获取内存信息
    memory = psutil.virtual_memory()
    memory_total = round(memory.total / (1024 ** 3), 2)  # 总内存，转换为GB并四舍五入到2位小数
    memory_used = round(memory.used / (1024 ** 3), 2)  # 已使用内存，转换为GB并四舍五入到2位小数
    memory_percent = memory.percent  # 内存使用百分比

    # 获取网络信息
    net_io = psutil.net_io_counters()
    bytes_sent = round(net_io.bytes_sent / (1024 ** 2), 2)  # 发送的字节数，转换为MB并四舍五入到2位小数
    bytes_recv = round(net_io.bytes_recv / (1024 ** 2), 2)  # 接收的字节数，转换为MB并四舍五入到2位小数

    # 构造返回的JSON数据
    data = {
        "总带宽速率": f"{round(bytes_sent + bytes_recv)} MB/秒",
        "上行带宽速率": f"{bytes_sent} MB/秒",
        "下行带宽速率": f"{bytes_recv} MB/秒",
        "CPU使用率": f"{cpu_usage}%",
        "总内存": f"{memory_total} GB",
        "已使用内存": f"{memory_used} GB",
        "内存使用率": f"{memory_percent}%"
    }

    # 返回系统性能指标的JSON对象
    return JSONResponse(content=data)


class RandomForestParams(BaseModel):
    n_estimators: int
    random_state: int
    min_samples_split: int
    min_samples_leaf: int
    bootstrap: bool


@app.get("/random_forest_params", response_model=RandomForestParams)
async def get_random_forest_params():
    return {
        "n_estimators": 100,
        "random_state": 42,
        "min_samples_split": 2,
        "min_samples_leaf": 1,
        "bootstrap": True
    }


class DatasetParam(BaseModel):
    LDAP: int
    random_state: int
    min_samples_split: int
    min_samples_leaf: int
    bootstrap: bool


@app.get("/dataset_param", response_model=DatasetParam)
async def get_random_forest_params():
    return {
        "n_estimators": 100,
        "random_state": 42,
        "min_samples_split": 2,
        "min_samples_leaf": 1,
        "bootstrap": True
    }


@app.get("/dataset_info")
async def get_dataset_info():
    try:
        # 打开并读取 JSON 文件
        with open("dataset_info.json", "r", encoding="utf-8") as file:
            data = json.load(file)
        return data
    except FileNotFoundError:
        # 如果文件不存在，返回404错误
        raise HTTPException(status_code=404, detail="Dataset info file not found")
    except json.JSONDecodeError:
        # 如果JSON文件格式错误，返回500内部服务器错误
        raise HTTPException(status_code=500, detail="Error decoding JSON")
    except Exception as e:
        # 其他错误，返回500内部服务器错误
        raise HTTPException(status_code=500, detail=str(e))


if __name__ == "__main__":
    uvicorn.run("main:app", host="127.0.0.1", port=8123, log_level="info")
